/**
 * @file Election.h
 * @author Benjamin Mayes <bdm8233@rit.edu>
 * @version 0.5
 *
 * @section LICENSE
 *
 * To Be Determined...
 * 
 * @section DESCRIPTION
 *
 * This is the header file of the Election class. The Election class represents an election that is as general as possible (i.e. a very large number of systems can be built on top of it). 
 */

#ifndef ELECTIONBASE_H_
#define ELECTIONBASE_H_
#include <map>
#include <set>
#include <vector>
#include <string>
#include <iostream>
using namespace std;

class ElectionBase {
    public:
        /**
         * The default constructor.
         *
         * Initializes all of the private members to default values and initializes the candidates and votes to empty lists.
         */
        ElectionBase();
        /**
         * The candidate constructor.
         *
         * Constructs an Election conisting of the candidates specified.
         *
         * @param candidates The candidates in the slection.
         */
        ElectionBase( const set<string>& candidates );
        virtual ~ElectionBase();
    public:
        /**
         * Adds a candidate to the election.
         *
         * @param candidate The candidate to add.
         * @return TODO - determine this.
         */
        virtual int add_candidate( const string& candidate ) = 0;
        /**
         * Removes a candidate from the election.
         *
         * @param candidate The candidate to remove.
         * @return TODO - determine this.
         */
        virtual int remove_candidate( const string& candidate ) = 0;

        /**
         * Obtains a set containing the names of all the candidates.
         *
         * @return A set containing the candidates in the election.
         */
        set<string> get_candidates()  const { 
            return candidates_;
        }
    public:
        /**
         * Counts all votes based on the positional scoring rule.
         */
        virtual void count_votes() = 0;
        /**
         * Obtains a set of all the winners of this election.
         *
         * @return A set of all winners of this election or an empty set if the votes are uncounted.
         */
        virtual set<string> get_winners() const = 0;
        /**
         * Obtains a set of all the candidates that the chosen candidate has more votes than.
         *
         * @param The candidate to compare to all candidates.
         * @return A set containing all candidates that the chosen candidate has more votes than.
         */
        virtual set<string> beats( const string& candidate ) const = 0;
        /**
         * Validates all the votes in the election.
         *
         * Checks to see if all the votes in the election are a complete ordering of the candidates in the election.
         *
         * @return 0 if there is at least one invalid vote in the election - 1 otherwise
         */
        virtual int validate_votes() const = 0;
        /**
         * Checks to see whether or not the election is valid.
         *
         * @return 1 if the election is valid, 0 otherwise.
         */
        int is_valid() const {
            return is_valid_;
        }
        int votes_counted() const {
            return votes_counted_;
        }
        /**
         * Erases all the votes within the Election.
         */
        virtual void erase_votes() = 0;
        /**
         * Displays the scores of the candidates and winners of the election
         * in a string format.
         *
         * @return The scores of all the candidates and the winner of the election
         * in a formatted string.
         */
        virtual string run_election() = 0;
        /**
         * Adds a vote to the election that is created interactively through
         * an input stream.
         *
         * @param in The input stream. If unspecified cin is used.
         */
        virtual void add_vote_interactive( istream& in = cin ) = 0;
        virtual int remove_vote_interactive( istream& in = cin ) = 0;
        virtual void add_random_votes( unsigned int n, int print_votes = 1 ) = 0;
        virtual void print_votes( ostream& out = cout ) = 0;
        /**
         * Allows for the front-end to interactively create election systems that
         * require additional parameters than just the candidate and voter sets.
         */
        virtual void interactive() {}
    protected:
        /**
         * Initializes the Election in a constructor independent manner.
         */
        virtual void init() = 0;
        /**
         * Erases the score-keeping data structure and recreates it from scratch.
         *
         * This function doubles as an initialization procedure.
         */
        virtual void clear_scores() = 0;
    protected:
        /**
         * The candidate set.
         */
        set<string> candidates_;
        /**
         * The removed candidate set.
         */
        set<string> removed_candidates_;
        int is_valid_;
        /**
         * boolean type variable used for determining whether or not votes are counted.
         */
        int votes_counted_;
};
#endif

